package net.towee.client.com.stuff.presenter;

import java.util.List;

import net.towee.client.com.stuff.GroupsCreator;
import net.towee.client.managers.GroupsManager;
import net.towee.model.account.Role;
import net.towee.model.group.GroupData;
import net.towee.model.group.GroupIdentity;
import net.towee.model.group.GroupOpenness;
import net.towee.model.group.GroupProfile;
import net.towee.model.group.impl.GroupDataImpl;
import net.towee.model.group.impl.GroupIdentityImpl;
import net.towee.model.utils.Pair;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.inject.Inject;

public class GroupsCreatorPresenter implements GroupsCreator, ClickHandler {

	public interface Display extends IsWidget {
		HasClickHandlers getCreateButton();
		
		// Data getters
		String getPrintName();
		String getAlias();
		String getHomeURL();
		String getDescription();
		GroupOpenness getOpenness();
		String getTestQuest();
		String getTestAnsw();
		List<Role> getRoles();
		List<Pair<String, String>> getExtendedProfile();
		Role getDefaultRole();
		
		// Errors
		void questTooShort(int minLength);
		void answTooShort(int minLength);
		void nameTooShort(int minLength);
		void aliasTooShort(int minLength);
		void descTooShort(int minLength);
		void emptyRole(Role r);
		void invalidURL();
		boolean hasErrors();

		// Events
		void onStartCreating();
		void onErrorCreating();
		void onEndCreating();
		
		void clearForm();
	}

	// Injected
	private final GroupsManager groupManager;
	private final Display display;
	
	// Min lengths
	private final int minQuestLength = 5;
	private final int minAnswLength  = 2;
	private final int nameLength     = 2;
	private final int descLength     = 20;
	
	@Inject
	public GroupsCreatorPresenter(GroupsManager manager, Display display){
		this.groupManager = manager;
		this.display = display;
		
		// Set handler for group creating button
		display.getCreateButton().addClickHandler(this);
	}

	@Override
	public void go(HasWidgets container) {
		container.clear();
		container.add( display.asWidget() );
	}

	@Override
	public void onClick(ClickEvent event) {
		// Validation
		if(display.getPrintName().length() < nameLength) display.nameTooShort(nameLength);
		if(display.getAlias().length() < nameLength) display.nameTooShort(nameLength);
		if(display.getDescription().length() < descLength) display.descTooShort(descLength);
		if(display.getTestQuest().length() < minQuestLength) display.descTooShort(minQuestLength);
		if(display.getTestAnsw().length() < minAnswLength) display.descTooShort(minAnswLength);
		
		// Create group if no errors
		if(!display.hasErrors()) {
			createGroup();
		}
	}
	
	private void createGroup() {
		display.onStartCreating();
		
		// Create group
		groupManager.createGroup(buildGroupData(), new AsyncCallback<GroupData>(){
			@Override
			public void onFailure(Throwable caught) {
				display.onErrorCreating();
			}

			@Override
			public void onSuccess(GroupData result) {
				display.onEndCreating();
			}
		});
	}

	private GroupData buildGroupData(){
		// Create data structure
		GroupIdentity identity = new GroupIdentityImpl(null, display.getPrintName(), display.getAlias());
		GroupData data = new GroupDataImpl(identity, display.getOpenness());
		GroupProfile profile = data.getProfile();

		// Add roles
		for (Role r : display.getRoles()) 
			data.getRoleContainer().addRole(r);
		
		// Set default role
		data.getRoleContainer().setDefaultRole( display.getDefaultRole() );

		// Add extended profile
		for (Pair<String, String> pair : display.getExtendedProfile()) {
			profile.addProfileArea(pair.getFirst(), pair.getSecond());
		}

		// Set default profile fields
		profile.setDescription(display.getDescription());
		profile.setHomeUrl(display.getHomeURL());

		// Set identity
		identity.setAlias(display.getAlias());
		identity.setPrintName(display.getPrintName());

		// Set test quest
		data.setTestQuestion(display.getTestQuest(), display.getTestAnsw());
		return data;
	}
}
